package cn.fcj.f20240328.fsocket.chanelhandler;

import cn.fcj.f20240328.fsocket.ReadDataEntity;
import cn.fcj.f20240328.fsocket.base.FBaseNIOSocket;
import cn.fcj.f20240328.fsocket.base.ISocketEventHandler;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * @项目名称:FSocket
 * @功能描述:实现事件处理接口，消息体结束符为 \n
 * @开发　者:mochhk
 * @邮　　箱:mochhk@163.com
 * @CreateDate:2024/4/5 13:31
 */
public class DEFSocketEventHandlerImp implements ISocketEventHandler {
    @Override
    public ByteBuffer sendData(SelectionKey key, byte[] msg) throws IOException {
        ByteBuffer byteBuffer = ByteBuffer.allocate(msg.length+1);
        byteBuffer.put(msg);
        byteBuffer.put((byte) ReadDataEntity.SPLIT);
        return byteBuffer;
    }

    @Override
    public void receiveDataForChannel(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(ReadDataEntity.BUFFER_LENGTH);
        ReadDataEntity.readBuffer(channel, readBuffer);
        ReadDataEntity readDataEntity = new ReadDataEntity();
        readBuffer.flip();
        while (!readForSpliteBody(channel, readBuffer, readDataEntity)) {
            ReadDataEntity.readBuffer(channel, readBuffer);
            readBuffer.flip();
        }
    }

    @Override
    public void exceptionHandler(Exception e, FBaseNIOSocket.ErrorCode errorCode, SelectionKey key) {

    }

    @Override
    public void onConnected(SelectionKey key) throws IOException {

    }

    private boolean readForSpliteBody(SocketChannel channel, ByteBuffer readBuffer, ReadDataEntity readDataEntity) throws IOException {
        readDataEntity.isFinished = false;
        byte[] tmp = null;
        int dataLen = findSplitPosition(readBuffer);
        System.out.println("=readForSpliteBody====dataLen==:" + dataLen + "===position()=:" + readBuffer.position()+"==limit()=:"+readBuffer.limit());
        if (dataLen == 0) {//发送的空消息
            readBuffer.clear();
            readDataEntity.isFinished = true;
        }
        else if (dataLen == -1)//说明现有数据中没有分割符
        {
            readDataEntity.isFinished = false;
        }
        else if (dataLen > 0)//有数据时
        {
            tmp = new byte[dataLen-readBuffer.position()];
            readBuffer.get(tmp);
            readBuffer.get();
            System.out.println("=readForSpliteBody====readBuffer.position()=:" + readBuffer.position()+" ==readBuffer.limit()=:"+readBuffer.limit());
            readDataEntity.byteBody = ReadDataEntity.byteMerger(readDataEntity.byteBody, tmp);
            System.out.println("readForSpliteBody==" + channel.getRemoteAddress().toString() + "=1==finished===:" + readDataEntity.bodyToString());
            readDataEntity.isFinished = true;
            if (readBuffer.position() < readBuffer.limit()) {
                ReadDataEntity rDataEntity = new ReadDataEntity();
                while (!readForSpliteBody(channel, readBuffer, rDataEntity)) {
                    ReadDataEntity.readBuffer(channel, readBuffer);
                    readBuffer.flip();
                }
                readBuffer.clear();
            } else {
                readBuffer.clear();
            }
        }
        if (!readDataEntity.isFinished) {
            tmp = new byte[readBuffer.limit() - readBuffer.position()];
            readBuffer.get(tmp);
            readDataEntity.byteBody = ReadDataEntity.byteMerger(readDataEntity.byteBody, tmp);
        }
        readBuffer.clear();
        return readDataEntity.isFinished;
    }

    /**
     * 获取分割符的位置
     *
     * @param readBuffer
     * @return
     */
    public int findSplitPosition(ByteBuffer readBuffer) {
        int start = readBuffer.position();
        int end = readBuffer.limit();
        System.out.println("=findSplitPosition=======readBuffer.limit()==:" + readBuffer.limit() + "====readBuffer.position()=:" + readBuffer.position());
        for (int i = start; i < end; i++) {
            byte splitchar = readBuffer.get(i);
            if (splitchar == ReadDataEntity.SPLIT) {
                return i;
            }
        }
        return -1;
    }
}
